package org.yanse.structures.array;

import java.util.Iterator;
import java.util.NoSuchElementException;

public class ArrayQueue<T> implements Iterable<T> {
    // 元素数组
    private final Object[] elements;

    // 数组默认容量
    private static final int DEFAULT_SIZE = 16;

    // 数组容量
    private final int size;

    // 元素个数
    private int count;

    public ArrayQueue() {
        size = DEFAULT_SIZE;
        elements = new Object[DEFAULT_SIZE];
        count = 0;
    }

    public ArrayQueue(int initCapacity) {
        if (initCapacity < 0) {
            throw new IllegalArgumentException();
        }

        size = initCapacity;
        elements = new Object[initCapacity];
        count = 0;
    }

    // 队尾添加元素，队列满抛出异常
    public boolean add(T ele) {
        if (count + 1 > size) {
            throw new IllegalStateException();
        }
        return offer(ele);
    }

    // 队尾添加元素，队列满返回false
    public boolean offer(T ele) {
        if (count + 1 > size) {
            return false;
        }
        elements[count++] = ele;
        return true;
    }

    // 移除并返回头部元素，队列空抛出异常
    public T remove() {
        if (isEmpty()) {
            throw new NoSuchElementException();
        }
        T head = (T)elements[0];
        for (int i = 1; i < count; i++) {
            elements[i - 1] = elements[i];
        }
        count--;
        return head;
    }

    // 移除并返回头部元素，队列空返回null
    public T poll() {
        if (isEmpty()) {
            return null;
        }
        return remove();
    }

    // 返回头部元素，队列空抛出异常
    public T element() {
        if (isEmpty()) {
            throw new NoSuchElementException();
        }
        return (T)elements[0];
    }

    // 返回头部元素，队列空返回null
    public T peek() {
        if (isEmpty()) {
            return null;
        }
        return element();
    }

    public boolean isEmpty() {
        return count == 0;
    }

    public int size() {
        return count;
    }

    public void clear() {
        for (int i = 0; i < count; i++) {
            elements[i] = null;
        }
        count = 0;
    }

    @Override
    public Iterator<T> iterator() {
        return new ArrayQueueIterator<>();
    }

    private class ArrayQueueIterator<T> implements Iterator<T> {
        private int currentIndex;

        @Override
        public boolean hasNext() {
            return currentIndex < count;
        }

        @Override
        public T next() {
            if (hasNext()) {
                return (T)elements[currentIndex++];
            }
            throw new UnsupportedOperationException("No more elements to iterate");
        }

        @Override
        public void remove() {
            if (currentIndex > 0) {
                poll();
                currentIndex--;
            }
            throw new IllegalStateException("remove() cannot be called before next()");
        }
    }
}
